﻿#include <conio.h>
#include <stdio.h>
#include <windows.h>
#include <time.h>
#include <mmsystem.h>
//#include <stdbool.h>

typedef enum {true=1, false=0} bool;

struct scors
{
	char nick[20];
	int points;
};

unsigned char tablica[70][10];           /*Tablica współrzędnych ekranu*/

int menu(void);  /*menu, zwraca wybrana opcje z menu*/
void ShowConsoleCursor(BOOL bShow);/*Funkcja pozwalająca ukryć kursor w czasie gry*/
void paletka_maluj(unsigned char id,unsigned char j,unsigned char i,unsigned char dlugosc);/*Funkcja malująca paletkę id==1 // gracz1 // id==2 gracz2*/
void pisz_punkty(unsigned char id, int punkty);/*Funkcja wypisująca punkty na ekranie*/
void clear(unsigned char x,unsigned char y, unsigned char typ);/*Funkcja usuwająca bloczki po trafieniu w nie*/
void make_block(bool mode,unsigned char x,unsigned char y);/*Funkcja losująca i malująca bloczki*/
void table_clear(void);/*Funkcja czyszcząca tablicę bloczków*/
void ramka(void); /*Funkcja rysująca ramkę*/
FILE *openFile(char *name, char *fMode); /*Uchwyt do pliku z punktami*/
void clearAll(bool mode, int j, int i, int dlugosc, int punkty);    /*Funkcja czyszcąca wszystko*/

void main()
{
	unsigned char dlugosc=7, dlugosc2=7;       /*Definicja długości paletki*/
	unsigned char x=24, y=10;                  /*Początkowe położenie piłeczki*/
	signed char dx=1, dy=1;                    /*Wektory przesunięcia*/
	unsigned char i=36, j=23;                  /*Położenie paletki pierwszego gracza*/
	unsigned char k=27, l=3;                   /*Położenie paletki drugiego gracza*/
	unsigned char a;                           /*Aktualnie wybrana opcja z menu*/
	unsigned char speed=150;                   /*Definicja prędkości piłki(inkrementowana co odbicie)*/
	unsigned char c=31;                        /*Kod ASCI piłki*/
	bool stop=false;                           /*Zmienna warunku końca gry*/
	bool mode=false;                           /*Ilosc graczy 0/false-1gracz  1/true-2graczy*/
	bool clr=false;
	unsigned char odbil=1;                     /*Identyfikator osoby która ostatnia odbyła piłkę*/
	unsigned char paletka;                     /*Zmienna sterująca pętlą rysującą paletkę*/
	int punkty=0, punkty2=0;         /*Zmienne zliczające liczbę punktów graczy*/
	unsigned char loop, loop2;                 /*Zmienne sterujące pętlą inicjalizacji tablicy*/
	int TSystemu, TPaletki=100, TBloczka=100, TPilki=300; /*Zmienne czasowe*/
	int temp;                                   /*Zmienna tymczasowa*/
	char nick[20], *temp1, *temp2;              /*Wskaźniki na zmienne pomocnicze*/
	FILE *scoreFile;                            /*Uchwyt do pliku*/
	struct scors playersScors[11]={0};          /*Struktura punktów z wynikami i nickami*/


	ramka();
	ShowConsoleCursor(false);       /*Wyłączenie widoczności kursora*/
	do
	{
		sndPlaySound("sound.wav", SND_ASYNC | SND_LOOP);
		a=menu();
		if(a==1)
		{
			/*Restart zmiennych*/
			stop=false;
			punkty=0;
			punkty2=0;
			odbil=1;
			x=24;
			y=10;
			dx=1;
			dy=1;
			speed=150;
			i=36; j=23;
			k=27; l=3;
			dlugosc=7;
			
			/* Pierwsze rysowanie paletki oraz wypisanie punktów pierwszego gracza */
			/*funkcja czysci ekran, tablice, wyswietla ramke, paletke i pkt*/
			clearAll(mode, i, j, dlugosc, punkty);

			/* Pierwsze rysowanie paletki oraz wypisanie punktow drugiego gracza*/
			if (mode==true)
			{
				pisz_punkty(mode+1, punkty2);
				paletka_maluj(mode+1,l,k,dlugosc2);
			}

			/*Główna pętla programu*/
			do
			{
				TSystemu=clock();   /*Obliczanie czasu systemowego*/
				if((TSystemu-TBloczka>300)) /*Sprawdzenie czasu od ostatniego losowania bloczka*/
				{
					TBloczka=clock();
					make_block(mode,x,y);
				}

				if((TSystemu-TPilki)>speed) /*Sprawdzenie czasu od ostatniego rysowania piłki*/
				{
					TPilki=clock();

					gotoxy(x-dx,y-dy);  /*Czyszczenie poprzedniego znaku*/
					printf(" ");

					gotoxy(x,y);        /*Rysowanie nowej piłki */
					printf("%c", c);
                    
					/* Sprawdzanie trafienia w bloczek rozbijalny*/
					if(tablica[x][y]!=0 && (((y>=2) && (y<=11) && x<69 && x>2) || (mode==1 && (y>=2) && (y<=11) && x<69 && x>2)))
					{
						if(tablica[x][y]==1 && dlugosc<15)    /*Efekt wydluzenia przy trafieniu w 1 dla gracza 1*/
						{
							dlugosc+=2;
							gotoxy(i,j);
							paletka_maluj(1,j,i,dlugosc);
                                                        ramka();
						}
                               
						if(tablica[x][y]==1 && odbil==2 && dlugosc2<15)    /*Efekt wydluzenia przy trafieniu w 1 dla gracza 2*/
						{
							dlugosc2+=2;
							gotoxy(k,l);
							paletka_maluj(2,l,k,dlugosc2);
							ramka();
						}
				
						if(odbil==1)pisz_punkty(1,punkty+=tablica[x][y]); /*Dodanie punktów w zależności od typu bloczka*/
						if(odbil==2)pisz_punkty(2,punkty+=tablica[x][y]);
                                
						clear(x,y,tablica[x][y]);
						dy=-dy;         /*Odwrocenie koordynatu Y*/
					}

					if(tablica[x][y]!=0 && (y>=5) && odbil==2 && (y<=16) && x<69 && x>2 && mode==true)
					{
						if(tablica[x][y]==1 && odbil==2 && dlugosc2<15)    /*Efekt wydluzenia przy trafieniu w 1 dla gracza 2*/
						{
							dlugosc2+=2;
							gotoxy(k,l);
							paletka_maluj(2,l,k,dlugosc2);
						}

                                                if(odbil==2)pisz_punkty(2,punkty+=tablica[x][y]);

						clear(x,y,tablica[x][y]);
						dy=-dy;         /*Odwrocenie koordynatu Y*/
					}



					/*Sprawdzenie trafienia w paletkę*/
					if(x>=i-1 && x<=i+dlugosc+1 && y==j-1)
					{
						if((x<i+dlugosc/2 && dx==1) || (x>=i+dlugosc/2 && dx==-1)) dx=-dx;
						dy=-dy;
						odbil=1;
						pisz_punkty(1,punkty+=1);
						if(speed>70)speed-=10;
					}
                
					/*Sprawdzenie trafienia w paletke drugiego gracza*/
					if(mode==true && x>=k-1 && x<=k+dlugosc+1 && y==l+1)
					{
						if((x<k+dlugosc2/2 && dx==1) || (x>=k+dlugosc2/2 && dx==-1)) dx=-dx;
						dy=-dy;
						odbil=2;
						pisz_punkty(2,punkty2+=1);
						if(speed>50) speed-=10;
					}

					/*Sprawdzenie trafienia w ściane boczną*/
					if (x==69||x==2)dx=-dx;
					if (y==2) dy=-dy;

					/*Sprawdzenie warunku kończącego grę*/
					if(y>=j || (mode==true && y<l))
					{
						clrscr();
						gotoxy(30,9);
						printf("GAME OVER");
						gotoxy(20,11);
						stop=true;
						
						//pobranie z i zapis 10 najlepszych wyników do pliku score.txt
						while(kbhit()) getch();  //Czyszczenie bufora klawiatury
						if(mode==false)
						{
							gotoxy(30,10);
							printf("Czy chcesz zapisac wynik (t/n)? ");
							temp1=(char*)getchar();
							getchar();
							if(temp1==(char*)'t' || temp1==(char*)'T')
							{
								clrscr();
								gotoxy(30,10);
								printf("Podaj imie: ");
								while(kbhit()) getch();
								scanf("%s", nick);
								getchar();
								scoreFile=openFile("score.txt", "a+");   //otwieranie pliku do odczytu
								for(i=0;fscanf(scoreFile, "%s - %s", &temp1, &temp2)!=EOF;i++)
								{
									if(i<10)
									{
										//pobieranie z pliku do struktury nazwy gracza
										strcpy(playersScors[i].nick, (char*)&temp1);
										//oraz ilosc punktow zdobytych
										playersScors[i].points=atoi((char*)&temp2);
									}
								}
								//dopisanie aktualnego gracza do tablicy z wynikami
								strcpy(playersScors[10].nick, nick);
								playersScors[10].points=punkty;
								//sortowanie tablicy wg. wynikow, malejąco
								for(i=0;i<10;i++)
									for(j=0;j<10-i;j++)
										if(playersScors[j].points<playersScors[j+1].points)
										{
											temp=playersScors[j].points;
											playersScors[j].points=playersScors[j+1].points;
											playersScors[j+1].points=temp;
											strcpy((char*)&temp2, playersScors[j].nick);
											strcpy(playersScors[j].nick, playersScors[j+1].nick);
											strcpy(playersScors[j+1].nick, (char*)&temp2);
										}
								fclose(scoreFile);

								scoreFile=openFile("score.txt", "w");     //otwieranie pliku do zapisu
								for(i=0;i<10;i++)
								{
									//zapisywanie 10 najlepszych wynikow do tablicy
									if(playersScors[i].points!=0)
									fprintf(scoreFile, "%s - %d\n", playersScors[i].nick, playersScors[i].points);
								}
								fclose(scoreFile);
							}
						}
						clrscr();
						///*Czyszczenie ekranu oraz tablicy bloczkow*/
						//clearAll(mode, i, j, dlugosc, punkty);
					}

					if(stop==false)
					{
						x+=dx;
						y+=dy;
					}
				}

				// unsigned cha rerakcja na wcisniecie strzalki
				if(TSystemu-TPaletki>50 && stop==false)
				{
					TPaletki=clock();

					if(punkty>100 && clr==false)
					{
						clearAll(mode, i, j, dlugosc, punkty);
						clr=true;
					}
                           
					if(GetKeyState(VK_LEFT)!=0 && GetKeyState(VK_LEFT)!=1)
					{
						gotoxy(i,j);
						for(paletka=1;paletka!=dlugosc+1;paletka++) printf(" ");
						if(i>dlugosc/2)i-=dlugosc/2;
						else i=2;
						paletka_maluj(1,j,i,dlugosc);
					}
		
					if(GetKeyState(VK_RIGHT)!=0 && GetKeyState(VK_RIGHT)!=1)
					{
						gotoxy(i,j);
						for(paletka=1;paletka!=dlugosc+1;paletka++) printf(" ");
						if(i<(68-dlugosc)) i+=dlugosc/2;
						else i=70-dlugosc;
						paletka_maluj(1,j,i,dlugosc);
					}
                              
					if(GetKeyState(0x41)!=0 && GetKeyState(0x41)!=1 && mode==1)
					{
						gotoxy(k,l);
						for(paletka=1;paletka!=dlugosc2+1;paletka++) printf(" ");
						if(k>dlugosc2)k-=dlugosc2/2;
						else k=2;
						paletka_maluj(2,l,k,dlugosc2);
					}

					if(GetKeyState(0x44)!=0 && GetKeyState(0x44)!=1 && mode==1)
					{
						gotoxy(k,l);
						for(paletka=1;paletka!=dlugosc2+1;paletka++) printf(" ");
						if(k<(67-dlugosc2)) k+=dlugosc2/2;
						else k=67-dlugosc2;
						paletka_maluj(2,l,k,dlugosc2);
					}
				}
			}while(c!='k' && stop!=true);
		}
		else if(a==2)
		{

            clrscr();
			gotoxy(29,3);
			printf("Najlepsze wyniki!!\n");
			scoreFile=openFile("score.txt", "a+");
			for(i=0;fscanf(scoreFile, "%s - %s\n", &temp1, &temp2)!=EOF;i++)
			{
				gotoxy(29,5+i);
				printf("%s - %s\n", &temp2, &temp1);
			}
			fclose(scoreFile);
            gotoxy(18, 24);
			system("pause");
		}
		else if(a==3)
		{
			clrscr();
        	gotoxy(29,12);
			printf("Ilosc graczy (1-2): ");
			temp=getchar();
			if(temp-48==2)
				mode=true;
			else if(temp-48==1)
				mode=false;
        }
    }while(a!=4);
}

int menu(void)//zwraca wybrana opcje z menu
{
	const int maxOpt=4;   //ilosc opcji w menu
	//key-wartość pobrana z klawiatury
	//checked-wskazuje wybrana opcje na ekranie
	//options-tablica z opcjami menu
	char key,*checked,options[4][20]={"Nowa gra", "Wyniki", "Ustawienia", "Wyjdz"};
	//i-dla petli for
	//marked-wybrana opcja menu
	//temp-zmienna pomocnicza
	int i,marked=1,temp;
       
	do
	{
		clrscr();
		gotoxy(33, 10);
		printf("Witaj w Arkanoidzie...\n");
		for(i=0;i<maxOpt;i++)
		{
			if(i+1==marked)
			{
				checked=">>";
				temp=2;
			}
			else
			{
				checked="";
				temp=0;
            }
			gotoxy(35-temp, 11+i*1);
			printf("%s %s\n", checked, options[i]);
		}
		key=getch();
		switch((int)key)
		{
		case 72:
			if(marked>1) marked--;
			break;
		case 80:
			if(marked<maxOpt) marked++;
			break;
        }
	}while((int)key!=13);
	return marked;
}

/*Funkcja pozwalająca ukryć kursor w czasie gry*/
void ShowConsoleCursor(BOOL bShow)
{
	static HANDLE hOut;               /*Uchwyt do wyjścia*/
	static BOOL firstTime=TRUE;       /*Domyślne wyświetlanie kursora*/
	CONSOLE_CURSOR_INFO cursorInfo;

	if( firstTime )
	{
		hOut=GetStdHandle( STD_OUTPUT_HANDLE );
		firstTime=FALSE;
	}
	cursorInfo.dwSize=10;
	cursorInfo.bVisible=bShow;

	SetConsoleCursorInfo( hOut,&cursorInfo );
}

/*Funkcja malująca paletkę id==1 // gracz1 // id==2 gracz2*/
void paletka_maluj(unsigned char id, unsigned char j, unsigned char i, unsigned char dlugosc)
{
	unsigned char paletka;                   /* Zmienna sterująca pętli*/
	unsigned char znak=4;                    /* Kod ASCI paletki*/

	gotoxy(i,j);
	for(paletka=1;paletka!=dlugosc+1;paletka++)
		printf("%c", znak);
	return;
}

/*Funkcja wypisująca punkty na ekranie*/
void pisz_punkty(unsigned char id, int punkty)
{
	if(id==1) gotoxy(3,24);
	if(id==2) gotoxy(3,2);
	printf("Punkty: %d ",punkty);
	return;
}

/*Funkcja usuwająca bloczki po trafieniu w nie*/
void clear(unsigned char x, unsigned char y, unsigned char typ)
{
    tablica[x][y]=0;
    if(tablica[x-1][y]==typ)
    {
        gotoxy(x-1,y);
        printf(" ");
        clear(x-1,y,typ);
    }
    if(tablica[x+1][y]==typ)
    {
        gotoxy(x+1,y);
        printf(" ");
        clear(x+1,y,typ);
    }
    return;
}

/*Funkcja losująca i malująca bloczki*/
void make_block(bool mode, unsigned char x, unsigned char y)
{
	unsigned char blockx, blocky,typ;         /*Zmienne koordynatów bloczka oraz jego typu*/
	unsigned char i;

	srand(time(0));                 /*Losowanie koordynatu X*/
	blockx=rand();
	srand(blockx+rand());
	blockx=2+rand()%68;
	if(mode==false)                     /*Określenie ilości graczy a co za tym idzie przesunięcia bloczkow*/
	{
		srand(time(0));         /*Losowanie koordynatu Y dla 1 gracza*/
		blocky=rand();
		srand(blocky+rand());
		blocky=2+rand()%9;
	}
	else
	{
		srand(time(0));         /*Losowanie koordynatu Y dla 2 graczy*/
		blocky=rand();
		srand(blocky+rand());
		blocky=4+rand()%11;
	}

	srand(time(0));                 /*Losowanie typu bloczka*/
	typ=1+rand()%9;

        if(blockx>=(67-typ))
        {
            blockx=67-typ;
        }
	//Sprawdzenie czy wylosowany bloczek nie znajduje się w tym samym miejscu co piłka
	if(blocky+1!=y && (x>(blockx+typ+1) || x<blockx) && x<(69-typ))
	{
		for(i=0;i<typ;i++)
		{
			if (tablica[blockx+i][blocky+1]==0)         /*Rysowanie bloczka*/
			{
				gotoxy(blockx+i,blocky+1);
				printf("%d",typ);
				tablica[blockx+i][blocky+1]=typ;
			}
		}
	}
}

/*Funkcja czyszcząca tablicę bloczków*/
void table_clear(void)
{
    unsigned char i,j;
    for(i=0;i<70;i++)
    {
        for(j=0;j<10;j++)
        {
            tablica[i][j]=0;
        }
    }
}

void ramka(void)    /*Funckja rysująca ramkę*/
{
        int i;
        for(i=0;i<69;i++)
        {
            gotoxy(i+1, 1);
            printf("%c", 205);
            if(i<24)
            {
                gotoxy(1,i+2);
                printf("%c", 186);
                gotoxy(70,i+2);
                printf("%c", 186);
            }
        }
        gotoxy(1,69);
        printf("%c", 187);
        gotoxy(1,1);
        printf("%c", 201);
}

FILE *openFile(char *name, char *fMode)     /*Funkcja otwierająca plik z wynikami*/
{
        FILE *fp;
        if((fp=fopen(name, fMode))==NULL)
        {
            fprintf(stderr, "Nie moge otworzyc pliku %s\n", name);
            exit(1);
        }
        return fp;
}

void clearAll(bool mode, int i, int j, int dlugosc, int punkty) /*Funkcja czyscząca*/
{
	clrscr();
	table_clear();
	paletka_maluj(mode+1,j,i,dlugosc);
	ramka();
	pisz_punkty(mode+1, punkty);
}